package com.yupi.yupao.interceptor;

import com.yupi.yupao.config.SessionFailoverConfig;
import com.yupi.yupao.constant.UserConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 会话自动延期拦截器
 * 每次用户有请求时，如果已登录则自动刷新会话
 * 增加Redis宕机时的本地会话缓存支持
 */
@Slf4j
public class SessionRenewalInterceptor implements HandlerInterceptor {

    @Autowired
    private SessionFailoverConfig sessionFailoverConfig;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 获取当前会话，false参数表示如果不存在则不创建新会话
        HttpSession session = request.getSession(false);
        
        // 如果会话存在且用户已登录，则刷新会话
        if (session != null && session.getAttribute(UserConstant.USER_LOGIN_STATE) != null) {
            // 记录当前会话数据
            Object userObj = session.getAttribute(UserConstant.USER_LOGIN_STATE);
            
            // 重新设置会话属性，触发会话访问，自动延长过期时间
            session.setAttribute(UserConstant.USER_LOGIN_STATE, userObj);
            
            // 检查是否需要使用本地缓存（Redis宕机情况）
            if (sessionFailoverConfig != null && sessionFailoverConfig.shouldUseLocalCache()) {
                // 当Redis不可用时，同时将会话数据存储到本地缓存
                sessionFailoverConfig.storeInLocalCache(session.getId(), userObj);
                log.debug("Redis不可用，会话数据已存储到本地缓存");
            } else {
                log.debug("用户已登录，自动延长会话时间");
            }
        } else if (session == null && sessionFailoverConfig != null && sessionFailoverConfig.shouldUseLocalCache()) {
            // 当Redis不可用，且会话为空时，尝试从本地缓存恢复会话
            String sessionId = extractSessionIdFromCookie(request);
            if (sessionId != null) {
                Object userObj = sessionFailoverConfig.getFromLocalCache(sessionId);
                if (userObj != null) {
                    // 创建新会话并恢复会话数据
                    HttpSession newSession = request.getSession(true);
                    newSession.setAttribute(UserConstant.USER_LOGIN_STATE, userObj);
                    log.info("从本地缓存恢复用户会话成功");
                }
            }
        }
        
        // 继续执行后续处理器
        return true;
    }
    
    /**
     * 从Cookie中提取会话ID
     */
    private String extractSessionIdFromCookie(HttpServletRequest request) {
        if (request.getCookies() == null) {
            return null;
        }
        
        for (javax.servlet.http.Cookie cookie : request.getCookies()) {
            if ("YUPAO_SESSION".equals(cookie.getName())) {
                return cookie.getValue();
            }
        }
        return null;
    }
} 